package com.cicadasmall.filter;

import com.cicadasmall.common.constant.Constant;
import com.cicadasmall.common.exception.ServiceException;
import com.cicadasmall.common.func.Fn;
import com.cicadasmall.security.support.ClientsUtils;
import com.cicadasmall.support.captch.ValidateCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * GlobalVerifyFilter
 *
 * @author Jin
 */
@Component
public class GlobalVerifyFilter extends GenericFilterBean {
    private ValidateCodeService imageValidateCodeService;
    private AuthenticationFailureHandler restLoginFailureHandler;

    private AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;

        String deviceId = httpServletRequest.getParameter(Constant.VALIDATE_PARAMETER_NAME_DEVICE_ID);
        String inputCodeValue = httpServletRequest.getParameter(Constant.VALIDATE_PARAMETER_NAME_CODE);

        try {
            if (pathMatcher.match("/oauth/token", httpServletRequest.getRequestURI()) && Fn.equal("POST", httpServletRequest.getMethod())) {
                String header = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
                String referer = httpServletRequest.getHeader("Referer");
                if (!Fn.isEmpty(header)) {
                    ClientsUtils.ClientInfo client = ClientsUtils.buildClientInfo(header);
                    //放行不做验证码校验
                    if (Fn.notEqual(Constant.VALIDATE_TEST_CLIENT, client.getClientId())) {
                        imageValidateCodeService.verifyCaptcha(deviceId, inputCodeValue);
                    }
                } else {
                    throw new ServiceException("无法获取clientId！");
                }
            }
        } catch (ServiceException serviceException) {
            restLoginFailureHandler.onAuthenticationFailure(httpServletRequest, httpServletResponse, new InsufficientAuthenticationException("验证码校验未通过！", serviceException));
            return;
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

    @Autowired
    public void setImageValidateCodeService(ValidateCodeService imageValidateCodeService) {
        this.imageValidateCodeService = imageValidateCodeService;
    }

    @Autowired
    public void setRestLoginFailureHandler(AuthenticationFailureHandler restLoginFailureHandler) {
        this.restLoginFailureHandler = restLoginFailureHandler;
    }
}
